package com.gemantic.task.dao.repository.impl;


import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;

import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Repository;

import com.gemantic.task.dao.constant.TaskStatus;
import com.gemantic.task.dao.local.TaskDao;
import com.gemantic.task.dao.repository.TaskRepository;
import com.gemantic.task.dto.ActiveTaskQueryParam;
import com.gemantic.task.dto.TaskQueryReqDto;
import com.gemantic.task.dto.TaskQueryRespDto;
import com.gemantic.task.model.Task;

/**
 * @author xiedi
 * @date 2022/09/15
 **/
@Repository
public class TaskRepositoryImpl implements TaskRepository {

    @Resource
    private TaskDao taskDao;

    @Override
    public List<Task> getActiveTasks(int total, int slice, Integer priority, int withinHours, int delayMinute, int selectLimit, Boolean withPending) {
        boolean withPendingStatus = false;
        if (withPending != null && withPending) {
            withPendingStatus = true;
        }

        ActiveTaskQueryParam param = ActiveTaskQueryParam.builder().total(total).delayMinute(delayMinute).selectLimit(selectLimit).withinHours(withinHours).priority(priority).slice(slice).withPending(withPendingStatus).build();
        return this.taskDao.getActiveTasks(param);
    }

    @Override
    public Task getTask(Task taskArg, Map<String, String> args) {
        return this.taskDao.selectByPrimaryKey(taskArg.getId());
    }

    @Override
    public Task lockTask(Task task) {
        return this.taskDao.lockByPrimaryKey(task.getId());
    }

    @Override
    public Task closeTask(Task task) {
        task.setStatus(TaskStatus.CLOSE.getCode());
        task.setRetryTimes(task.getRetryTimes() + 1);
        return this.updateTask(task);
    }

    @Override
    public void closeTask(String orderNo, String taskType, String remark) {
        this.taskDao.closeTask(orderNo, taskType, remark);
    }

    @Override
    public Task retryTask(Task task, Date nextRunTime) {
        task.setStatus(TaskStatus.OPEN.getCode());
        task.setNextRunTime(nextRunTime);
        task.setRetryTimes(task.getRetryTimes() + 1);
        task = this.updateTask(task);
        return task == null ? null : task;
    }

    @Override
    public Task terminateTask(Task task) {
        task.setRetryTimes(task.getRetryTimes() + 1);
        task.setStatus(TaskStatus.TERMINATED.getCode());
        return this.updateTask(task);
    }

    @Override
    public Task runningTask(Task task, int delayMinutes) {
        task.setStatus(TaskStatus.RUNNING.getCode());
        task.setNextRunTime(DateUtils.addMinutes(new Date(), Math.abs(delayMinutes)));
        return this.updateTask(task);
    }

    @Override
    public Task postponeTask(Task task, Date nextRunTime) {
        task.setStatus(TaskStatus.OPEN.getCode());
        task.setNextRunTime(nextRunTime);
        task = this.updateTask(task);
        return task == null ? null : task;
    }

    @Override
    public Task createTask(Task task) {
        task.setResponseData("");
        task.setRemark("");
        task.setCreateTime(new Date());
        task.setRetryTimes(0);
        int rows = this.taskDao.insertSelective(task);
        return rows == 0 ? null : task;
    }

    @Override
    public Task updateTask(Task task) {
        task.setVersion(task.getVersion() + 1);
        int rows = this.taskDao.updateByPrimaryKey(task);
        return rows == 0 ? null : task;
    }

    @Override
    public List<Task> getOpenTask() {
        return this.taskDao.getOpenTask();
    }

    @Override
    public List<Task> getOpenTaskByOrder(String orderNo, String taskType) {
        return this.taskDao.getOpenTaskByOrder(orderNo, taskType);
    }

    public int pendTask(Task task) {
        return this.taskDao.pendTask(task.getId(), task.getStatus(), task.getVersion());
    }

    @Override
    public Task getTaskById(long taskId) {
        return this.taskDao.selectByPrimaryKey(taskId);
    }

    @Override
    public TaskQueryRespDto getTasks(TaskQueryReqDto reqDto) {
        TaskQueryRespDto respDto = new TaskQueryRespDto();
        respDto.setCurrent((long) reqDto.getPageNo());
        respDto.setSize((long) reqDto.getPageSize());
        List<List<Task>> result = this.taskDao.getTasks(reqDto);
        respDto.setRecords((List) result.get(0));
        respDto.setTotal((Long) ((List) result.get(1)).get(0));
        return respDto;
    }

    @Override
    public void batchUpdate(Date nextRunTime, String status, List<Long> tasks) {
        this.taskDao.batchUpdate(nextRunTime, status, tasks);
    }

    @Override
    public Task modifyTaskFromUI(Task task) {
        int rows = taskDao.modifyTaskFromUI(task);
        if (rows == 0) {
            return null;
        }
        return task;
    }

    @Override
    public List<Task> getAllTaskByOrder(String orderNo, String taskType) {
        return this.taskDao.getAllTaskByOrder(orderNo, taskType);
    }
}
